﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Net.Security;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using HengTong.Model.Db;
using HengTong.Model.Db.System;
using HengTong.Model.Extension;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using TiaoTaoHelper.Extension.String;
using TiaoTaoHelper.Models;
using UUIDNext;
using WalkingTec.Mvvm.Core;

namespace HengTong.Model.Services;

public interface ISmsAuthService
{
    Task<Result<string>> SendCodeAsync(string mobile, string templateType = "default");
    Result<bool> VerifyCode(string mobile, string code);
    Task<Result<string>> SendAsync(string mobile, string content);
    Task<Result<string>> SendAndLog(string mobile, string content);
}

public class SmsAuthService : ISmsAuthService
{
    private readonly WTMContext _context;
    private readonly IMemoryCache _memoryCache;
    private readonly ILogger<SmsAuthService> _logger;
    private readonly string _secretName;
    private readonly string _secretKey;
    private readonly string _shost;
    private readonly string _smsTemplate;

    public SmsAuthService(ILogger<SmsAuthService> logger, WTMContext context, IMemoryCache memoryCache)
    {
        _logger = logger;
        _context = context;
        _memoryCache = memoryCache;

        var siteConfig = context.GetSiteConfig();
        _secretKey = siteConfig.SmsSecretKey;
        _secretName = siteConfig.SmsSecretName;
        _shost = siteConfig.SmsHost;
        _smsTemplate = siteConfig.SmsTemplate;
        if (string.IsNullOrWhiteSpace(_secretKey) || string.IsNullOrWhiteSpace(_secretName) ||
            string.IsNullOrWhiteSpace(_shost))
        {
            _logger.LogError("短信服务配置不完整，请检查配置文件");
            throw new Exception("短信服务配置不完整，请检查配置文件");
        }

        if (string.IsNullOrWhiteSpace(_smsTemplate))
        {
            _logger.LogWarning("短信模板未配置，将使用默认模板");
        }
    }

    /// <summary>
    /// 发送短信验证码
    /// </summary>
    /// <param name="mobile"></param>
    /// <returns></returns>
    public async Task<Result<string>> SendCodeAsync(string mobile, string templateType = "default")
    {
        var cacheKey = $"{nameof(SendCodeAsync)}_{mobile}";
        var code = _memoryCache.Get<string>(cacheKey);
        if (!string.IsNullOrWhiteSpace(code))
        {
            return new Result<string>("请勿重复发送验证码");
        }

        code = new Random().Next(100000, 999999).ToString();
        _memoryCache.Set($"{nameof(SendCodeAsync)}_{mobile}", code, TimeSpan.FromMinutes(5));
        //您的验证码是{s6}, 请在{s1}分钟内输入.
        //var content = $"您的验证码是{code}, 请在5分钟内输入.";

        string content;
        if (string.IsNullOrWhiteSpace(_smsTemplate))
        {
            content = $"您的验证码是{code}, 请在5分钟内输入.";
        }
        else
        {
            try
            {
                var templates = JsonConvert.DeserializeObject<Dictionary<string, string>>(_smsTemplate);
                var template = templates.ContainsKey(templateType)
                    ? templates[templateType]
                    : templates.GetValueOrDefault("default", "您的验证码是{code}, 请在5分钟内输入.");
                content = template.Replace("{code}", code);
            }
            catch
            {
                // 如果不是JSON格式，当作单个模板处理
                content = _smsTemplate.Replace("{code}", code);
            }
        }

        _logger.LogInformation($"发送验证码: {mobile} - {content}");
        return await SendAndLog(mobile, content);
    }

    /// <summary>
    /// 校验验证码
    /// </summary>
    /// <param name="mobile"></param>
    /// <param name="code"></param>
    /// <returns></returns>
    public Result<bool> VerifyCode(string mobile, string code)
    {
        var cacheKey = $"{nameof(SendCodeAsync)}_{mobile}";
        _logger.LogInformation($"验证码校验: 手机号={mobile}, 验证码={code}");
        if (_memoryCache.TryGetValue(cacheKey, out string cachedCode))
        {
            _logger.LogInformation($"缓存中的验证码: {cachedCode}");
            if (cachedCode == code)
            {
                _memoryCache.Remove(cacheKey);
                _logger.LogInformation("验证码验证成功");
                return new Result<bool>()
                {
                    Code = 200,
                    Message = "验证码验证成功",
                    Data = true
                };
            }

            _logger.LogWarning("验证码错误");
            return new Result<bool>()
            {
                Code = 400,
                Message = "验证码错误",
                Data = false
            };
        }

        _logger.LogWarning("验证码不存在或已过期");
        return new Result<bool>()
        {
            Code = 404,
            Message = "验证码不存在或已过期",
            Data = false
        };
    }


    /// <summary>
    /// 发送短信
    /// </summary>
    /// <param name="mobile"></param>
    /// <param name="content"></param>
    /// <returns></returns>
    public async Task<Result<string>> SendAsync(string mobile, string content)
    {
        var secretName = _secretName;
        var secretKey = _secretKey;
        var host = _shost;
        _logger.LogInformation($"开始发送短信: 手机号={mobile}, 内容={content}");
        if (string.IsNullOrWhiteSpace(_secretName))
        {
            _logger.LogError("短信发送失败: secretName不能为空");
            return new Result<string>("secretName不能为空");
        }

        if (string.IsNullOrWhiteSpace(_secretKey))
        {
            _logger.LogError("短信发送失败: secretKey不能为空");
            return new Result<string>("secretKey不能为空");
        }

        if (string.IsNullOrWhiteSpace(_shost))
        {
            _logger.LogError("短信发送失败: host不能为空");
            return new Result<string>("host不能为空");
        }

        var pattern = @"^1\d{10}$";
        if (!Regex.IsMatch(mobile, pattern))
        {
            _logger.LogWarning($"短信发送失败: 手机号格式错误 - {mobile}");
            return new Result<string>("请检查手机号码是否正确");
        }

        var postData = new
        {
            secretName,
            secretKey,
            mobile,
            content
        };
        try
        {
            var handler = new SocketsHttpHandler
            {
                SslOptions = new SslClientAuthenticationOptions()
                {
                    RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true
                }
            };
            var helper = new HttpClient(handler);
            _logger.LogInformation($"发送短信API请求: URL={host}/Sms/Api/Send, 手机号={mobile}");
            var response = await helper.PostAsJsonAsync($"{host}/Sms/Api/Send", postData);
            if (!response.IsSuccessStatusCode)
            {
                var errorMsg = $"短信API通讯失败: StatusCode={response.StatusCode}, ReasonPhrase={response.ReasonPhrase}";
                _logger.LogError(errorMsg);
                throw new Exception(errorMsg);
            }

            var json = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"短信API响应: {json}");
            if (!json.TryJsonParse(out SmsSendResponse result, out var error))
            {
                var errorMsg = $"短信API通讯失败: StatusCode={response.StatusCode}, ReasonPhrase={response.ReasonPhrase}";
                _logger.LogError(errorMsg);
                return new Result<string>($"格式化返回数据出错: {error}");
            }

            if (result.code == 0)
            {
                _logger.LogInformation($"短信发送成功: 手机号={mobile}, 响应消息={result.msg}");
                return new Result<string>
                {
                    Code = 200,
                    Message = "success",
                    Data = result.msg
                };
            }

            var failureMsg = $"短信发送失败: code={result.code}, msg={result.msg}, 手机号={mobile}";
            _logger.LogError(failureMsg);
            return new Result<string>($"短信发送失败: {result.msg}");
        }
        catch (Exception ex)
        {
            var errorMsg = $"短信发送异常: 手机号={mobile}, 异常信息={ex.Message}";
            _logger.LogError(ex, errorMsg);
            return new Result<string>($"短信发送异常: {ex.Message}");
        }
    }

    /// <summary>
    /// 发送短信并记录到数据库
    /// </summary>
    /// <param name="mobile"></param>
    /// <param name="content"></param>
    /// <returns></returns>
    public async Task<Result<string>> SendAndLog(string mobile, string content)
    {
        var result = await this.SendAsync(mobile, content);
        var pushLog = new SysSmsAuthLog()
        {
            ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
            Phone = mobile,
            SmsTime = DateTime.Now,
            State = result.Code == 200 ? PushStateEnum.成功 : PushStateEnum.失败,
            Message = result.Message,
            Context = content,
        };
        await _context.DC.Set<SysSmsAuthLog>().AddAsync(pushLog);
        await _context.DC.SaveChangesAsync();
        return result;
    }

    public class SmsSendResponse
    {
        [JsonRequired] public int code { get; set; }

        public string msg { get; set; }

        public string data { get; set; }
    }
}